import router from '@/router'
import store from '@/store'
export interface Principle {
  user: User;
  roles: Role[];
  authorities: Authority[];
}

export interface User {
  username: string;
  cname: string;
  [key: string]: any;
}

export interface Role {
  roleName: string;
  roleCode: string;
  [key: string]: any;
}

export interface Authority {
  pid: string;
  [key: string]: any;
}

export interface AuthOptions {
  principleLoader?: () => Promise<Principle>;

  logoutHandler?: () => Promise<string>;

  loginHandler?: (params: LoginParams) => Promise<any>;

  // 是否开启权限控制
  accessEnabled?: false;
}

export interface LoginParams {
  identifier: string;
  credential: string;
  type: 'phone' | 'username' | 'ding_talk';
}

export default class Auth {
  constructor (options: AuthOptions = {}) {
    this.options = options
  }

  options: AuthOptions

  principle: Principle | null = null

  get username (): string {
    return this.principle?.user?.username || ''
  }

  get cname (): string {
    return this.principle?.user?.cname || ''
  }

  get roles (): Role[] {
    return this.principle?.roles || []
  }

  get authorities (): Authority[] {
    return this.principle?.authorities || []
  }

  get authenticated (): boolean {
    return !!this.principle
  }

  hasAnyRole (...roles: string[]): boolean {
    return roles.some(v => this.roles.some(w => w.roleCode === v))
  }

  hasAllRole (...roles: string[]): boolean {
    return roles.every(v => this.roles.some(w => w.roleCode === v))
  }

  // 前往登录页面
  toLogin (loginUrl: string, logout = false) {
    this.principle = null // 删除认证实体
    const u = new URL(location.href)
    const r = (u.protocol.startsWith('app:') ? (u.protocol + (u.host || '')) : u.origin) +
            (u.pathname || '') + '#/login'
    location.assign(r)
  }

  // 控制访问
  access (pid: string): Promise<boolean> {
    if (this.authenticated) {
      const has = this.contain(pid)
      return Promise.resolve(has)
    } else {
      return new Promise((resolve, reject) => {
        this.loadPrinciple().then(() => {
          const has = this.contain(pid)
          resolve(has)
        }).catch((e: Error) => {
          reject(e)
        })
      })
    }
  }

  // 同步控制访问
  accessSync (pid: string): boolean {
    return this.contain(pid)
  }

  // 退出
  logout () {
    if (!this.options?.logoutHandler) throw new Error('please specific logoutHandler')
    this.options.logoutHandler().then(data => {
      this.toLogin('/login', true)
    }).catch(() => {
      this.toLogin('/login', true)
    })
  }

  // 登录
  login (params: LoginParams) {
    if (!this.options?.loginHandler) throw new Error('please specific loginHandler')
    return this.options.loginHandler(params).then(data => {
      router.push('/')
      return data
    })
  }

  // 加载用户信息
  load (refresh = false): Promise<Principle> {
    if (this.authenticated && !refresh) return Promise.resolve(this.principle as Principle)
    return this.loadPrinciple()
  }

  private loadPrinciple (): Promise<Principle> {
    if (this.options?.principleLoader) {
      return this.options.principleLoader().then(data => {
        this.principle = data
        return this.principle
      })
    }
    throw Error('please specific PrincipleLoader')
  }

  private contain (pid: string): boolean {
    if (!this.options?.accessEnabled) return true
    return this.authorities.some(v => v.pid === pid)
  }
}
